/*
 * Copyright (c) 2010, Michael Hengler (developer (at) hengler (dot) de),
 * Nikolaus Moll (developer (at) miblounge (dot) net).
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of the Jombi project nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL JOMBI BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package net.miblounge.jombi.impl.widgets;

import java.util.List;

import net.miblounge.jombi.impl.util.BorderToComposite;
import net.miblounge.jombi.impl.util.ColorUtil;
import net.miblounge.jombi.impl.util.ScrollBarSettingsConvert;
import net.miblounge.jombi.impl.widgets.util.ChildRemover;
import net.miblounge.miglayout.qt.MigLayout;

import org.jowidgets.common.color.IColorConstant;
import org.jowidgets.common.types.Cursor;
import org.jowidgets.common.types.Dimension;
import org.jowidgets.common.types.Position;
import org.jowidgets.common.types.Rectangle;
import org.jowidgets.common.widgets.IControlCommon;
import org.jowidgets.common.widgets.controller.IComponentListener;
import org.jowidgets.common.widgets.controller.IFocusListener;
import org.jowidgets.common.widgets.controller.IKeyListener;
import org.jowidgets.common.widgets.controller.IMouseListener;
import org.jowidgets.common.widgets.controller.IPopupDetectionListener;
import org.jowidgets.common.widgets.descriptor.IWidgetDescriptor;
import org.jowidgets.common.widgets.factory.ICustomWidgetCreator;
import org.jowidgets.common.widgets.factory.IGenericWidgetFactory;
import org.jowidgets.common.widgets.layout.ILayoutDescriptor;
import org.jowidgets.spi.widgets.IPopupMenuSpi;
import org.jowidgets.spi.widgets.IScrollCompositeSpi;
import org.jowidgets.spi.widgets.setup.IScrollCompositeSetupSpi;

import com.trolltech.qt.core.QSize;
import com.trolltech.qt.gui.QFrame.Shape;
import com.trolltech.qt.gui.QGroupBox;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QPalette;
import com.trolltech.qt.gui.QPalette.ColorRole;
import com.trolltech.qt.gui.QScrollArea;
import com.trolltech.qt.gui.QWidget;

public class ScrollCompositeImpl implements IScrollCompositeSpi {

	private final QtComposite outerContainer;
	private final QtContainer innerContainer;

	public ScrollCompositeImpl(
		final Object parentUiReference,
		final IGenericWidgetFactory factory,
		final IScrollCompositeSetupSpi setup) {

		final String growingCellConstraints = "grow, w 0::,h 0::";

		final QWidget parent;
		if (parentUiReference instanceof QMainWindow) {
			parent = ((QMainWindow) parentUiReference).centralWidget();
		} else {
			parent = (QWidget) parentUiReference;
		}

		final QWidget outerComposite = BorderToComposite.convert(setup.getBorder());
		outerComposite.setParent(parent);

		final MigLayout outerLayout = new MigLayout("", "0[grow, 0::]0", "[grow, 0::]");
		outerComposite.setLayout(outerLayout);

		this.outerContainer = new QtComposite(factory, outerComposite);

		final QScrollArea scrollPane = new QScrollArea(outerComposite) {
			@Override
			public QSize sizeHint() {
				final QSize result;
				if (this.widget() != null) {
					result = this.widget().sizeHint();
				} else {
					result = super.sizeHint();
				}
				return result;
			}
		};
		scrollPane.setFrameShape(Shape.NoFrame);
		scrollPane.setWidgetResizable(true);
		scrollPane.setVerticalScrollBarPolicy(ScrollBarSettingsConvert.convertVertical(setup));
		scrollPane.setHorizontalScrollBarPolicy(ScrollBarSettingsConvert.convertHorizontal(setup));
		outerLayout.addWidget(scrollPane, growingCellConstraints);

		//final QtContainer scrolledWidget = new QtContainer(factory, scrollPane);

		final QWidget innerComposite = new QWidget(scrollPane) {

			@Override
			public String toString() {
				return "QWidget [innerComposite]";
			}

			@Override
			public QSize sizeHint() {
				final QSize result;
				result = super.sizeHint();
				if ((result.width() >= 0) && (result.height() >= 0)) {
					this.setMinimumSize(result);
				}
				return result;
			}
		};

		// fix palette
		if (getUiReference() instanceof QGroupBox) {
			final QPalette innerPalette = outerComposite.palette();
			innerPalette.setColor(ColorRole.WindowText, ColorUtil.getDefaultColor(ColorRole.WindowText));
			innerComposite.setPalette(innerPalette);
		}

		this.innerContainer = new QtContainer(factory, innerComposite);

		scrollPane.setWidget(innerComposite);
	}

	@Override
	public final void setLayout(final ILayoutDescriptor layout) {
		innerContainer.setLayout(layout);
	}

	@Override
	public QWidget getUiReference() {
		return outerContainer.getUiReference();
	}

	@Override
	public void redraw() {
		outerContainer.redraw();
	}

	@Override
	public void setForegroundColor(final IColorConstant colorValue) {
		innerContainer.setForegroundColor(colorValue);
	}

	@Override
	public void setBackgroundColor(final IColorConstant colorValue) {
		innerContainer.setBackgroundColor(colorValue);
	}

	@Override
	public <WIDGET_TYPE extends IControlCommon> WIDGET_TYPE add(
		final Integer index,
		final IWidgetDescriptor<? extends WIDGET_TYPE> descriptor,
		final Object layoutConstraints) {
		return innerContainer.add(index, descriptor, layoutConstraints);
	}

	@Override
	public <WIDGET_TYPE extends IControlCommon> WIDGET_TYPE add(
		final Integer index,
		final ICustomWidgetCreator<WIDGET_TYPE> creator,
		final Object layoutConstraints) {
		return innerContainer.add(index, creator, layoutConstraints);
	}

	@Override
	public void layoutBegin() {
		outerContainer.layoutBegin();
	}

	@Override
	public void layoutEnd() {
		outerContainer.layoutEnd();
	}

	@Override
	public void removeAll() {
		innerContainer.removeAll();
	}

	@Override
	public void setVisible(final boolean visible) {
		getUiReference().setVisible(visible);
	}

	@Override
	public boolean isVisible() {
		return getUiReference().isVisible();
	}

	@Override
	public boolean remove(final IControlCommon control) {
		return ChildRemover.removeChild(innerContainer.getUiReference(), (QWidget) control.getUiReference());
	}

	@Override
	public IColorConstant getForegroundColor() {
		return innerContainer.getForegroundColor();
	}

	@Override
	public IColorConstant getBackgroundColor() {
		return innerContainer.getBackgroundColor();
	}

	@Override
	public Dimension getSize() {
		return outerContainer.getSize();
	}

	@Override
	public void setCursor(final Cursor cursor) {
		outerContainer.setCursor(cursor);
	}

	@Override
	public void setEnabled(final boolean enabled) {
		outerContainer.setEnabled(enabled);
		innerContainer.setEnabled(enabled);
	}

	@Override
	public boolean isEnabled() {
		return outerContainer.isEnabled();
	}

	@Override
	public IPopupMenuSpi createPopupMenu() {
		return innerContainer.createPopupMenu();
	}

	@Override
	public void addPopupDetectionListener(final IPopupDetectionListener listener) {
		innerContainer.addPopupDetectionListener(listener);
	}

	@Override
	public void removePopupDetectionListener(final IPopupDetectionListener listener) {
		innerContainer.removePopupDetectionListener(listener);
	}

	@Override
	public void setLayoutConstraints(final Object layoutConstraints) {
		outerContainer.setLayoutConstraints(layoutConstraints);
	}

	@Override
	public Object getLayoutConstraints() {
		return outerContainer.getLayoutConstraints();
	}

	@Override
	public Position getPosition() {
		return outerContainer.getPosition();
	}

	@Override
	public void setPosition(final Position position) {
		outerContainer.setPosition(position);
	}

	@Override
	public void setSize(final Dimension size) {
		outerContainer.setSize(size);
	}

	@Override
	public void setRedrawEnabled(final boolean enabled) {
		outerContainer.setRedrawEnabled(enabled);
	}

	@Override
	public boolean requestFocus() {
		return innerContainer.requestFocus();
	}

	@Override
	public void addFocusListener(final IFocusListener listener) {
		innerContainer.addFocusListener(listener);
	}

	@Override
	public void removeFocusListener(final IFocusListener listener) {
		innerContainer.removeFocusListener(listener);
	}

	@Override
	public void addKeyListener(final IKeyListener listener) {
		innerContainer.addKeyListener(listener);
	}

	@Override
	public void removeKeyListener(final IKeyListener listener) {
		innerContainer.removeKeyListener(listener);
	}

	@Override
	public void addComponentListener(final IComponentListener componentListener) {
		innerContainer.addComponentListener(componentListener);
	}

	@Override
	public void removeComponentListener(final IComponentListener componentListener) {
		innerContainer.removeComponentListener(componentListener);
	}

	@Override
	public void addMouseListener(final IMouseListener mouseListener) {
		innerContainer.addMouseListener(mouseListener);
	}

	@Override
	public void removeMouseListener(final IMouseListener mouseListener) {
		innerContainer.removeMouseListener(mouseListener);
	}

	@Override
	public Dimension getMinSize() {
		return outerContainer.getMinSize();
	}

	@Override
	public Dimension getPreferredSize() {
		return outerContainer.getPreferredSize();
	}

	@Override
	public Dimension getMaxSize() {
		return outerContainer.getMaxSize();
	}

	@Override
	public Rectangle getClientArea() {
		return innerContainer.getClientArea();
	}

	@Override
	public Dimension computeDecoratedSize(final Dimension clientAreaSize) {
		return outerContainer.computeDecoratedSize(clientAreaSize);
	}

	@Override
	public void setToolTipText(final String toolTip) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setTabOrder(final List<? extends IControlCommon> tabOrder) {
		innerContainer.setTabOrder(tabOrder);
	}
}
